package com.momoc.netty.frame.handler;

import com.google.protobuf.MessageLite;
import com.google.protobuf.MessageLiteOrBuilder;
import com.momoc.netty.frame.FrameMethodUtils;
import com.momoc.netty.frame.config.SmartNettyProperties;
import com.momoc.netty.frame.context.ProtobufHandlerMappingContext;
import com.momoc.netty.frame.dispatch.model.PacketMassageInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * proto消息发送编码，发送protobuf消息出站
 * @author momoc
 * @version 1.0
 * @className ProtobufEnCoderHandler
 * @description
 * @date 2023/7/5 18:54
 */
public class ProtobufEnCoderHandler extends MessageToMessageEncoder<MessageLiteOrBuilder> {


    static Logger log = LoggerFactory.getLogger(ProtobufEnCoderHandler.class);
    @Override
    protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder invoke, List<Object> out) throws Exception {
        ByteBuf buf = encode(invoke);
        WebSocketFrame frame = new BinaryWebSocketFrame(buf);
        ctx.writeAndFlush(frame);
    }

    public ByteBuf encode(MessageLiteOrBuilder invoke) {
        Class<? extends MessageLiteOrBuilder> aClass = invoke.getClass();
        String name = aClass.getName();
        String[] classNameArr = name.split("_");
        int msgId = Integer.parseInt(classNameArr[1]);
        byte[] responseMsgByte = ProtobufHandlerMappingContext.getResponseMsgByte(msgId);
        ByteBuf buf = null;
        if (invoke instanceof MessageLite) {
            byte[] bytes = ((MessageLite) invoke).toByteArray();
            buf = Unpooled.wrappedBuffer(responseMsgByte, bytes);
        } else {
            if (invoke instanceof MessageLite.Builder) {
                byte[] bytes = ((MessageLite.Builder) invoke).build().toByteArray();
                buf = Unpooled.wrappedBuffer(responseMsgByte, bytes);
            }
        }
        return buf;
    }

    /**
     * 用来还原出站序列化的对象的信息
     * @param byteBuf 二进制
     * @param msgIdLength 消息号长度
     * @return
     */
    public static PacketMassageInfo getResponseMessageInfo(ByteBuf byteBuf, Integer msgIdLength) {

        // 一个字节八位，所以要除以8
        int readMsgLength = msgIdLength / 8;
        Integer msgId = FrameMethodUtils.getMessageId(byteBuf, readMsgLength);
        //读消息号，目前消息号大小是16位，最多能定义65535个消息。
        PacketMassageInfo packetMassageInfo = ProtobufHandlerMappingContext.getResponsePacketInfoByMessageId(msgId);
        if (packetMassageInfo == null) {
            log.error(" This message does not  support, msgId:{}", msgId);
            return null;
        }
        return packetMassageInfo;
    }


    public static PacketMassageInfo getResponseMessageInfo(ByteBuf buf) {
        return getResponseMessageInfo(buf, SmartNettyProperties.getNettyProperties().getMsgIdLength());
    }
}
